package com.nulstudio.sppm.entity;

import com.nulstudio.sppm.exception.NulException;
import com.nulstudio.sppm.exception.NulExceptionConstants;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;

import java.util.Date;
import java.util.Objects;
import java.util.Random;

public final class NulInvite {

    private static final String INVITE_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    private static final int INVITE_CODE_LENGTH = 6;

    private int id;

    private String code;

    private Date expireTime;

    private int roleId;

    private int remaining;

    private boolean blocked;


    public NulInvite() {
        this.id = 0;
        this.code = null;
        this.expireTime = null;
        this.roleId = 0;
        this.remaining = 0;
        this.blocked = false;
    }

    public NulInvite(String code, Date expireTime, int roleId, int remaining, boolean blocked) {
        this.id = 0;
        this.code = code;
        this.expireTime = expireTime;
        this.roleId = roleId;
        this.remaining = remaining;
        this.blocked = blocked;
    }

    public static void assertValidity(@Nullable NulInvite invite) throws NulException {
        if (invite == null)
            throw new NulException(NulExceptionConstants.INVALID_INVITE_CODE);
        if (invite.isBlocked())
            throw new NulException(NulExceptionConstants.INVITE_CODE_BLOCKED);
        if (invite.getRemaining() <= 0)
            throw new NulException(NulExceptionConstants.INVITE_CODE_USED_UP);
        if (invite.getExpireTime().before(new Date()))
            throw new NulException(NulExceptionConstants.EXPIRED_INVITE_CODE);
    }

    @NonNull
    public static String generate() {
        final StringBuilder stringBuilder = new StringBuilder(INVITE_CODE_LENGTH);
        final Random random = new Random();
        final int characterCount = INVITE_CHARACTERS.length();
        for (int i = 0; i < INVITE_CODE_LENGTH; ++i) {
            stringBuilder.append(INVITE_CHARACTERS.charAt(random.nextInt(characterCount)));
        }
        return stringBuilder.toString();
    }

    public int getId() {
        return id;
    }

    public String getCode() {
        return code;
    }

    public Date getExpireTime() {
        return expireTime;
    }

    public int getRoleId() {
        return roleId;
    }

    public int getRemaining() {
        return remaining;
    }

    public boolean isBlocked() {
        return blocked;
    }

    public void setId(int id) {
        this.id = id;
    }

    private void setCode(String code) {
        this.code = code;
    }

    private void setExpireTime(Date expireTime) {
        this.expireTime = expireTime;
    }

    private void setRoleId(int roleId) {
        this.roleId = roleId;
    }

    private void setRemaining(int remaining) {
        this.remaining = remaining;
    }

    private void setBlocked(boolean blocked) {
        this.blocked = blocked;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        final NulInvite nulInvite = (NulInvite) o;
        return roleId == nulInvite.roleId && remaining == nulInvite.remaining
                && blocked == nulInvite.blocked && Objects.equals(code, nulInvite.code)
                && Objects.equals(expireTime, nulInvite.expireTime) && id == nulInvite.id;
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, code, expireTime, roleId, remaining, blocked);
    }
}
